home *** CD-ROM | disk | FTP | other *** search
/ E.M.Computergraphic Phase 4 / Phase 4 - Desktop Video Dreams (E. M. Computergraphic)(1996).iso / utilities / multiplay / noteplayer / notehard.asm < prev    next >
Assembly Source File  |  1996-01-03  |  7KB  |  248 lines

  1. * notehard.asm - NotePlayer that directly uses the Amiga audio hardware
  2. * Copyright 1992 Bryan Ford
  3. * See distribution terms in NotePlayer.doc
  4. * $Id: notehard.asm,v 1.1 92/05/15 15:08:26 BAF Exp $
  5.  
  6.         include "exec/types.i"
  7.         include "hardware/custom.i"
  8.         include "hardware/dmabits.i"
  9.         include "bry/macros.i"
  10.  
  11. VERSION         equ     1       ; Version of Player.doc this NotePlayer is written for
  12. REVISION        equ     0
  13.  
  14. CLOCK           equ     3579545
  15.  
  16. CUSTOM          equ     $dff000
  17.  
  18.         code    text
  19.  
  20. *** NoteHard - Jump table providing the hardware NotePlayer interface
  21.         xdef    NoteHard,_NoteHard
  22. NoteHard
  23. _NoteHard
  24.         jmp     noteinfo(pc)
  25.         jmp     noteinit(pc)
  26.         jmp     notefinish(pc)
  27.         jmp     notestart(pc)
  28.         jmp     notestop(pc)
  29.         jmp     notefreqvol(pc)
  30.         jmp     notefreq(pc)
  31.         jmp     notevol(pc)
  32.  
  33. *** NoteHardDMACall - Pointer to routine client needs to call after about 7 scanlines, or NULL
  34.         xdef    NoteHardDMACall,_NoteHardDMACall
  35. NoteHardDMACall
  36. _NoteHardDMACall
  37.                 ds.l    1
  38.  
  39. *** noteinfo - Return information about this note player
  40. noteinfo
  41.         lea     \noteinfo(pc),a0
  42.         move.l  a0,d0
  43.         rts
  44.  
  45. \noteinfo
  46.         dc.b    VERSION
  47.         dc.b    REVISION
  48.         dc.b    3 ; NOTEF_CHIPSAMPLES!NOTEF_PERIOD
  49.         dc.b    4
  50.         dc.l    \noteplayername
  51. \noteinfoend
  52.  
  53. \noteplayername         dc.b    "Amiga hardware NotePlayer",0
  54.         even
  55.  
  56. *** noteinit - Initialize the note player
  57. * d0.b = Number of channels needed (1-128) (ignored)
  58. * a0 = Stereo orientation (ignored)
  59. * Returns: d0 = Zero if successful, pointer to error message on failure
  60. noteinit
  61.         moveq   #0,d0
  62.         ; fall through...
  63. *** notefinish - Shut down the note player
  64. notefinish
  65.         lea     CUSTOM,a0
  66.         move.w  #DMAF_AUDIO,dmacon(a0)
  67.         clr.w   aud0+ac_dat(a0)
  68.         clr.w   aud1+ac_dat(a0)
  69.         clr.w   aud2+ac_dat(a0)
  70.         clr.w   aud3+ac_dat(a0)
  71.         rts
  72.  
  73. *** findchan - Find hardware channel address
  74. * d2.b = Channel number
  75. * Returns:
  76. * a1 = Channel address
  77. * a0/d0 = Saved
  78. findchan
  79.         moveq   #0,d1
  80.         move.b  d2,d1
  81.         lsl.w   #4,d1
  82.         lea     CUSTOM+aud0,a1
  83.         adda.w  d1,a1
  84.         rts
  85.  
  86. *** notestop - Stop any currently playing note in a channel
  87. * May be called from interrupt code level 4 or lower
  88. * d2.b = Channel number
  89. notestop
  90.         moveq   #0,d0
  91.         moveq   #0,d1
  92.         ; fall through...
  93. *** notestart - Start playing a note immediately
  94. * May be called from interrupt code level 4 or lower
  95. * d2.b = Channel number
  96. * a0 = One-shot sample data
  97. * d0.l = One-shot sample length (0 if no one-shot part)
  98. * a1 = Repeat sample data
  99. * d1.l = Repeat sample length (0 if no repeat part)
  100. * d3.w = Sample frequency (if 0, then high word contains period)
  101. * d4.w = Volume at which to play sample (0-$100)
  102. notestart
  103.         move.l  a1,-(sp)
  104.         move.w  d1,-(sp)
  105.  
  106.         or.w    d0,d1                           ; See if we're just turning the note off
  107.         bz      \noteoff
  108.  
  109.         bsr     findchan
  110.  
  111.         bsr     calcper
  112.         bsr     calcvol
  113.  
  114.         lsr.w   #1,d0                           ; Stuff the one-shot pointers
  115.         bnz     \hasoneshot
  116.         moveq   #2,d0
  117.         sub.l   a0,a0
  118. \hasoneshot
  119.         move.l  a0,ac_ptr(a1)
  120.         move.w  d0,ac_len(a1)
  121.  
  122.         moveq   #0,d0                           ; Turn DMA for this channel off
  123.         bset    d2,d0
  124.         move.w  d0,CUSTOM+dmacon
  125.  
  126.         move.w  (sp)+,d1                        ; Find repeat part (a1/d1.w)
  127.         move.l  (sp)+,a1
  128.         lsr.w   #1,d1
  129.         bnz     \hasrepeat
  130.         moveq   #2,d1
  131.         sub.l   a1,a1
  132. \hasrepeat
  133.  
  134.         lea     \dmaflags(pc),a0                ; Save the information we'll need later
  135.         or.w    d0,(a0)
  136.         move.b  d2,d0
  137.         add.w   d0,d0
  138.         move.w  d1,\repeatlen-\dmaflags(a0,d0.w)
  139.         add.w   d0,d0
  140.         move.l  a1,\repeatptr-\dmaflags(a0,d0.w)
  141.  
  142.         lea     \dma1(pc),a0                    ; Client will call us back after about 7 scanlines
  143.         move.l  a0,NoteHardDMACall ; -\dmaflags(a0)  FIXME
  144.         rts
  145.  
  146. \dma1
  147.         move.w  #DMAF_SETCLR,d0                 ; Turn DMA on
  148.         or.w    \dmaflags(pc),d0
  149.         move.w  d0,CUSTOM+dmacon
  150.  
  151.         lea     \dma2(pc),a0                    ; Wait another 7 scanlines or so
  152.         move.l  a0,NoteHardDMACall
  153.         rts
  154.  
  155. \dma2
  156.         lea     CUSTOM,a0                       ; Set the repeat pointers
  157.         move.w  \dmaflags(pc),d0
  158.         lsr.w   #1,d0
  159.         bcc     \dmano0
  160.         move.l  \repeatptr+4*0(pc),aud0+ac_ptr(a0)
  161.         move.w  \repeatlen+2*0(pc),aud0+ac_len(a0)
  162. \dmano0
  163.         lsr.w   #1,d0
  164.         bcc     \dmano1
  165.         move.l  \repeatptr+4*1(pc),aud1+ac_ptr(a0)
  166.         move.w  \repeatlen+2*1(pc),aud1+ac_len(a0)
  167. \dmano1
  168.         lsr.w   #1,d0
  169.         bcc     \dmano2
  170.         move.l  \repeatptr+4*2(pc),aud2+ac_ptr(a0)
  171.         move.w  \repeatlen+2*2(pc),aud2+ac_len(a0)
  172. \dmano2
  173.         lsr.w   #1,d0
  174.         bcc     \dmano3
  175.         move.l  \repeatptr+4*3(pc),aud3+ac_ptr(a0)
  176.         move.w  \repeatlen+2*3(pc),aud3+ac_len(a0)
  177. \dmano3
  178.         clr.l   NoteHardDMACall
  179.         clr.w   \dmaflags
  180.         rts
  181.  
  182. \dmaflags       ds.w    1
  183. \repeatlen      ds.w    4
  184. \repeatptr      ds.l    4
  185.  
  186. \noteoff
  187.         addq    #6,sp
  188.  
  189.         moveq   #0,d0                           ; Turn DMA for this channel off
  190.         bset    d2,d0
  191.         move.w  d0,CUSTOM+dmacon
  192.         rts
  193.  
  194. *** calcper - Calculate period and insert it in an IOAudio
  195. * a1 = Hardware channel
  196. * d3.l = Frequency/period value
  197. * a0/a1/d0 = Saved
  198. calcper
  199.         tst.w   d3
  200.         bnz     \freq
  201.         swap    d3
  202.         move.w  d3,ac_per(a1)
  203.         swap    d3
  204.         rts
  205. \freq
  206.         move.l  #CLOCK,d1
  207.         divu.w  d3,d1
  208.         move.w  d1,ac_per(a1)
  209.         rts
  210.  
  211. *** calcvol - Calculate volume and insert it in an IOAudio
  212. * a1 = Hardware channel
  213. * d4.w = Volume (0-$100)
  214. * a0/a1/d0 = Saved
  215. calcvol
  216.         move.w  d4,d1
  217.         lsr.w   #2,d1
  218.         move.w  d1,ac_vol(a1)
  219.         rts
  220.  
  221. *** notefreqvol - Change the frequency and volume of the currently playing note
  222. * May be called from interrupt code level 4 or lower
  223. * d2.b = Channel number
  224. * d3.w = New sample frequency (if 0, then high word contains period)
  225. * d4.w = New volume (0-$100)
  226. notefreqvol
  227.         bsr     findchan
  228.         bsr     calcper
  229.         bra     calcvol
  230.  
  231. *** notefreq - Change the frequency of the currently playing note
  232. * May be called from interrupt code level 4 or lower
  233. * d2.b = Channel number
  234. * d3.w = New sample frequency (if 0, then high word contains period)
  235. notefreq
  236.         bsr     findchan
  237.         bra     calcper
  238.  
  239. *** notevol - Change the volume of the currently playing note
  240. * May be called from interrupt code level 4 or lower
  241. * d2.b = Channel number
  242. * d4.w = New volume (0-$100)
  243. notevol
  244.         bsr     findchan
  245.         bra     calcvol
  246.  
  247.         end
  248.